#ifndef _NE_MESH_H_
#define _NE_MESH_H_

#include <graphics/SubMesh.h>
#include <graphics/Material.h>
#include <graphics/VertexData.h>

namespace ne
{
    class NEAPI Mesh : public Resource
    {
        public:
            Mesh(ResourceManager *pManager,
                 const uint64_t id,
                 const std::string &name,
                 const std::string &fileName,
                 const bool isManual,
                 ManualResourceLoader *pLoader);

            void setVertexData(const VertexDataPtr &pVertexData);

            VertexDataPtr getVertexData() const;

            bool addChild(const SubMeshPtr &pChild);

            void removeChild(const SubMeshPtr &pChild);

            void removeChild(const std::string &name);

            void removeAllChildren();

            SubMeshPtr getChild(const std::string &name) const;

            size_t getChildrenCount() const;

            const SubMeshMap& getChildrenMap() const;

            void setMaterial(const MaterialPtr &pMaterial);

            MaterialPtr getMaterial() const;

            virtual ~Mesh();

        protected:
            virtual bool loadImplement();

            virtual bool unloadImplement();

            virtual bool downloadImplement();

            virtual size_t _calculateSize() const;

        private:
            VertexDataPtr mpVertexData;
            SubMeshMap mChildren;
            MaterialPtr mpMaterial;
    };

    class NEAPI MeshPtr : public SharedPtr<Mesh>
    {
        public:
            MeshPtr() : SharedPtr<Mesh>() {}
            explicit MeshPtr(Mesh *pMesh) : SharedPtr<Mesh>(pMesh) {}
            MeshPtr(const MeshPtr &pMesh) : SharedPtr<Mesh>(pMesh) {}

            MeshPtr(const ResourcePtr &p)
                : SharedPtr<Mesh>()
            {
                mpPtr = static_cast<Mesh*>(p.ptr());
                mpUseCount = p.getUseCountPtr();
                if (mpUseCount)
                {
                    ++(*mpUseCount);
                }
            }

            MeshPtr& operator = (const ResourcePtr &p)
            {
                if (mpPtr == static_cast<Mesh*>(p.ptr()))
                {
                    return *this;
                }
                MeshPtr temp(p);
                swap(temp);
                return *this;
            }
    };
}

#endif
